package com.exonline.front.controller.teacher;

import cn.hutool.core.util.IdUtil;
import com.exonline.commons.base.IBaseServlet;
import com.exonline.commons.dao.DaoImpl;
import com.exonline.commons.dao.IDao;
import com.exonline.commons.entity.Courses;
import com.exonline.commons.entity.Teacher;
import com.exonline.commons.utils.QiNiuUploadUtils;
import com.exonline.commons.utils.TokenUtils;
import com.exonline.commons.entity.Student;
import com.exonline.commons.entity.TInfo;
import com.exonline.front.controller.teacher.TeacherService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.*;

/**
 * @desc 教师模块的C层
 * @author hbrj
 */

@WebServlet("/font/teacher")
public class TeacherServlet extends HttpServlet implements IBaseServlet {
    // 使用Jackson库进行JSON格式的响应输出
    ObjectMapper mapper = new ObjectMapper();
    // 教师类，用于处理课程相关业务逻辑
    TeacherService service = new TeacherService();
    // 学生类，用于处理学生相关业务逻辑
    IDao<Student> studentDao = new DaoImpl<>();
    // 七牛云工具类
    static QiNiuUploadUtils qiNiuUploadUtils = new QiNiuUploadUtils();
    // 上传配置
    private static final int MEMORY_THRESHOLD   = 1024 * 1024 * 3;  // 3MB
    private static final int MAX_FILE_SIZE      = 1024 * 1024 * 40; // 40MB
    private static final int MAX_REQUEST_SIZE   = 1024 * 1024 * 1024 ; // 1024MB
    /**
     * @desc  重写service方法，根据请求中的method参数调用不同的处理方法
     * @param req  客户端请求
     * @param resp 服务端响应
     * @throws ServletException 如果请求处理过程中发生错误
     * @throws IOException 如果响应过程中发生I/O错误
     */
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        String method = req.getParameter("method");
        try {
            if ("query".equals(method)) {
                this.query(req, resp);
            } else if ("queryone".equals(method)) {
                this.queryOne(req, resp);
            } else if ("add".equals(method)) {
                this.add(req, resp);
            } else if ("edit".equals(method)) {
                this.edit(req, resp);
            } else if ("delete".equals(method)) {
                this.delete(req, resp);
            } else if ("info".equals(method)) {
                this.info(req, resp);
            } else if ("teacherSearch".equals(method)) {
                this.teacherSearch(req,resp);
            }
        } catch (Exception e) {
            throw new ServletException(e);
        }
    }

    /**
     * @desc  1.查询所有教师的方法
     * @param req  请求参数
     * @param resp 响应数据
     * @throws SQLException 如果数据库查询出错
     * @throws IOException 如果响应过程中发生I/O错误
     */
    @Override
    public void query(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        // 从请求中获取页码参数
        int pageno = Integer.parseInt(req.getParameter("pageno"));
        // 调用service层方法查询教师列表
        List<Teacher> teachers = service.queryAll(1,pageno);
        //响应
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);
        map.put("msg", "查询成功");
        map.put("data", teachers);
        mapper.writeValue(resp.getWriter(),map);
    }

    /**
     * @desc  2.根据id查询教师信息的方法
     * @param req  请求参数
     * @param resp 响应数据
     * @throws SQLException 如果数据库查询出错
     * @throws IOException 如果响应过程中发生I/O错误
     */
    @Override
    public void queryOne(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        // 获取id 参数
        String id = req.getParameter("id");
        service.queryOne(id);
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);
        map.put("msg", "查询成功");
        map.put("data", id);
        mapper.writeValue(resp.getWriter(), map);
    }
    /**
     * @desc  7. 根据课程名称进行模糊查询，添加教师可按自己课程查询（传入tid）
     * @param req
     * @param resp
     */
    private void teacherSearch(HttpServletRequest req, HttpServletResponse resp) {
        try {
            // 获取前端传递的课程名参数，假设参数名为 "courseName"，可根据实际调整
            String courseName = req.getParameter("courseName");
            // 判断课程名是否为空
            if (courseName == null || courseName.trim().isEmpty()) {
                Map<String, Object> map = new HashMap<>();
                map.put("code", 400);
                map.put("msg", "请输入有效的课程名进行查询");
                map.put("data", null);
                mapper.writeValue(resp.getWriter(), map);
                return;
            }
            // 获取前端传递的教师编号tid参数，假设参数名为 "tid"，可根据实际调整
            String tid = req.getParameter("tid");
            if (tid == null || tid.trim().isEmpty()) {
                Map<String, Object> map = new HashMap<>();
                map.put("code", 400);
                map.put("msg", "请输入有效的教师编号进行查询");
                map.put("data", null);
                mapper.writeValue(resp.getWriter(), map);
                return;
            }
            // 获取Service实例
            TeacherService service = new TeacherService();

            // 调用Service层的方法进行 模糊查询 ，传入课程名和教师编号
            List<Courses> courses = service.searchCourses(courseName, tid);

            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("code", 200);
            resultMap.put("msg", "课程名模糊查询成功");
            resultMap.put("data", courses);

            // 将查询结果转换为JSON格式并写入响应
            mapper.writeValue(resp.getWriter(), resultMap);
        } catch (IOException e) {
            e.printStackTrace();
            try {
                Map<String, Object> errorMap = new HashMap<>();
                errorMap.put("code", 500);
                errorMap.put("msg", "课程名模糊查询过程中出现错误");
                errorMap.put("data", null);
                mapper.writeValue(resp.getWriter(), errorMap);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * @desc  6. 教师的系统的  数据统计  ( 销售量  总收入  课程访问量)
     * @param req
     * @param resp
     */
    private void info(HttpServletRequest req, HttpServletResponse resp) throws IOException, SQLException {
        // 调用service层方法 getInfo
        TInfo tinfo = service.getInfo(req);
        mapper.writeValue(resp.getWriter(),tinfo);
    }


    /**
     * @desc  5. 删除教师的方法
     * @param req
     * @param resp
     * @throws SQLException
     * @throws IOException
     */
    @Override
    public void delete(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        String id = req.getParameter("id");
        service.deleteById(id);
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);
        map.put("msg", "删除成功");
        map.put("data", id);
        mapper.writeValue(resp.getWriter(), map);
    }


    /**
     * @desc  4. 更改编辑相关老师的方法
     * @param req  请求参数
     * @param resp 响应数据
     * @throws SQLException 如果数据库查询出错
     * @throws IOException 如果响应过程中发生I/O错误
     */
    @Override
    public void edit(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        // 获取相关参数
        String id = req.getParameter("id");
        String name = req.getParameter("tname");
        String workyears = req.getParameter("workyears");
        String direction = req.getParameter("direction");
        String introduction = req.getParameter("introduction");
        String email = req.getParameter("email");
        String phone = req.getParameter("phone");
        String password = req.getParameter("password");
        // 调用Service层方法进行更新
        service.update(id, name, workyears, direction, introduction, email, phone, password);
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);
        map.put("msg", "添加成功");
        map.put("data", id);
        mapper.writeValue(resp.getWriter(), map);
    }

    /**
     * @desc  3. 添加教师信息申请入驻
     * @param req  请求参数
     * @param resp 响应数据
     * @throws SQLException 如果数据库查询出错
     * @throws IOException 如果响应过程中发生I/O错误
     */
    @Override
    public void add(HttpServletRequest req, HttpServletResponse resp) throws SQLException, IOException {
        // 生成教师id
        String id = IdUtil.simpleUUID();
        // 从Session中获取学生id
        String sid = TokenUtils.getId(req);
        // 检查学生id是否为空
        if (sid == null) {
            // 如果未能从Session获取到学生id，返回错误信息
            Map<String, Object> map = new HashMap<>();
            map.put("code", 201);
            map.put("msg", "未能从Session中获取到学生id，请检查相关设置");
            map.put("data", null);
            mapper.writeValue(resp.getWriter(), map);
            return;
        }
        // 根据获取到的学生id去学生表查询密码
        String studentPassword = getStudentPasswordById(sid);
        if (studentPassword == null) {
            // 如果查询学生密码失败，返回错误信息
            Map<String, Object> map = new HashMap<>();
            map.put("code", 202);
            map.put("msg", "查询学生密码失败，请检查数据库连接或相关逻辑");
            map.put("data", null);
            mapper.writeValue(resp.getWriter(), map);
            return;
        }
        // 从请求参数中获取教师信息(传入相关教师信息的参数)
        String name = req.getParameter("tname");  // 教师姓名
        String workyears = req.getParameter("workyears");  // 工作年限
        String direction = req.getParameter("direction"); // 教学方向
        String introduce = req.getParameter("introduce"); // 教师介绍
        String email = req.getParameter("email"); // 邮箱
        String phone = req.getParameter("phone"); // 电话

        // 调用honorUpload的方法处理荣誉图片上传，并获取上传后图片的路径列表
        List<String> urlList = doUrl(req, resp);

        // 调用Service层方法添加教师记录，传入相应参数，并设置status为0（待审核）
        service.add(id, name, workyears, direction, introduce, email, phone, studentPassword, 0);

        // 获取刚插入教师记录的id（假设Service层的add方法返回插入后的教师id，或者通过其他方式获取，此处简单示例一种情况）
        String tid = getIdOfNewlyInsertedTeacher(id);

        // 将荣誉图片路径保存到honorpicture表中，关联对应的教师id
        if (tid!= null &&!urlList.isEmpty()) {
            saveHonorPicturesToDb(tid, urlList,resp);
        }

        // 返回成功信息
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);
        map.put("msg", "教师申请及荣誉图片添加成功");
        map.put("data", id);
        mapper.writeValue(resp.getWriter(), map);
    }

    /**
     * @desc
     * @param insertedTeacherId
     * @return
     */
    private String getIdOfNewlyInsertedTeacher(String insertedTeacherId) {
        // 这里简单返回传入的id，实际情况可能需要根据数据库插入操作后的返回值或者再次查询来准确获取刚插入教师的id
        return insertedTeacherId;
    }

    /**
     * @desc  将荣誉图片路径保存到honorpicture表中，关联对应的教师id
     */
    private void saveHonorPicturesToDb(String tid, List<String> urlList, HttpServletResponse resp) {
        try {
            List<Map<String, String>> DataUrlList = new ArrayList<>();
            for (String pictureUrl : urlList) {
                String id = IdUtil.simpleUUID();
                Map<String, String> DataUrl = new HashMap<>();
                DataUrl.put("id", id);
                DataUrl.put("tid", tid);
                DataUrl.put("pictureUrl", pictureUrl);

                // 将视频数据添加到列表中
                DataUrlList.add(DataUrl);
                service.saveHonorPicture(id, tid, pictureUrl);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                Map<String, Object> errorMap = new HashMap<>();
                errorMap.put("code", 500);
                errorMap.put("msg", "保存荣誉图片到数据库时出现错误");
                errorMap.put("data", null);
                mapper.writeValue(resp.getWriter(), errorMap);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
    /**
     * @desc  通过学生id获取学生密码
     */
    private String getStudentPasswordById(String sid) {
        try {
            // 假设studentIDao是用于操作学生表的数据库访问对象，已经正确初始化
            String sql = "SELECT password FROM student WHERE id = ?";
            List<Map<String, Object>> result = studentDao.queryWithPagingAndConditions(sql, null, 1, 1, new MapListHandler(),sid);
            if (!result.isEmpty()) {
                return (String) result.get(0).get("password");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * @desc  上传荣誉图片
     * @param request  请求参数
     * @param response 响应数据
     * @throws SQLException 如果数据库查询出错
     * @throws IOException 如果响应过程中发生I/O错误
     */
    public static List<String> doUrl(HttpServletRequest request, HttpServletResponse response) throws  IOException {

        List<String> urlList = new ArrayList<>();
        {
            System.out.println(request.getParameter("id"));
            // 检测是否为多媒体上传
            if (!ServletFileUpload.isMultipartContent(request)) {
                // 如果不是则停止
                PrintWriter writer = response.getWriter();
                writer.println("Error: 表单必须包含 enctype=multipart/form-data");
                writer.flush();
                return null;
            }

            // 配置上传参数
            DiskFileItemFactory factory = new DiskFileItemFactory();
            // 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
            factory.setSizeThreshold(MEMORY_THRESHOLD);
            // 设置临时存储目录
            factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

            ServletFileUpload upload = new ServletFileUpload(factory);

            // 设置最大文件上传值
            upload.setFileSizeMax(MAX_FILE_SIZE);

            // 设置最大请求值 (包含文件和表单数据)
            upload.setSizeMax(MAX_REQUEST_SIZE);

            // 中文处理
            upload.setHeaderEncoding("UTF-8");

            try {
                // 解析请求的内容提取文件数据
                @SuppressWarnings("unchecked")
                List<FileItem> formItems = upload.parseRequest(request);

                if (formItems!= null && formItems.size() > 0) {
                    // 迭代表单数据
                    for (FileItem item : formItems) {
                        // 处理不在表单中的字段
                        if (!item.isFormField()) {
                            // 上传文件到七牛云并获取返回的URL
                            String url = qiNiuUploadUtils.uploadFiles(item.getInputStream(), item.getName());

                            if (url!= null) {

                                urlList.add(url);

                                // 创建一个Map来存储要返回给前端的信息
                                Map<String, Object> resultMap = new HashMap<>();
                                resultMap.put("status", "success");
                                resultMap.put("message", "上传成功");
                                resultMap.put("url", url);


                                // 将Map转换为JSON格式并返回给前端
                                ObjectMapper mapper = new ObjectMapper();
                                mapper.writeValue(response.getWriter(), resultMap);
                            } else {
                                Map<String, Object> resultMap = new HashMap<>();
                                resultMap.put("status", "failure");
                                resultMap.put("message", "上传失败");

                                ObjectMapper mapper = new ObjectMapper();
                                mapper.writeValue(response.getWriter(), resultMap);
                            }
                        }
                    }
                }
            } catch (Exception ex) {
                // 处理上传过程中出现的异常情况
                request.setAttribute("message", "错误信息: " + ex.getMessage());

                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("status", "failure");
                resultMap.put("message", "上传过程中出现错误");

                ObjectMapper mapper = new ObjectMapper();
                mapper.writeValue(response.getWriter(), resultMap);
            }
        }
        return urlList;
    }
}
